Sharpen relational reasoning: set-based querying, joins, aggregation, windows, normalization, indexing & transaction semantics.
Data as relations (tables) with keys ensuring integrity.
Primary key uniquely identifies row. Foreign key enforces referential link.
1NF atomic, 2NF full dependency, 3NF remove transitive, BCNF stronger determinants.
Performance trade: duplicates for fewer joins; maintain with routines or views.
NOT NULL, UNIQUE, CHECK, DEFAULT, FOREIGN KEY; enforce invariants at storage.
CREATE TABLE users(
id SERIAL PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE orders(
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id),
total_cents INT CHECK(total_cents >= 0)
);
Think in sets; express desired result not loops.
SELECT u.email, o.total_cents
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE o.total_cents > 5000
ORDER BY o.total_cents DESC;
Summarize data then layer analytic context & consistency.
SELECT user_id,
total_cents,
SUM(total_cents) OVER (PARTITION BY user_id ORDER BY id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS rolling_3
FROM orders;
Accelerate lookups, maintain write cost awareness.
CREATE INDEX idx_orders_user_total ON orders(user_id,total_cents);
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id=5 AND total_cents>1000;
Client-side simulations only.
Reusable structural templates.
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER(
PARTITION BY user_id ORDER BY total_cents DESC) rn
FROM orders
) t WHERE rn <= 3;INSERT INTO users(id,email)
VALUES(1,'a@x')
ON CONFLICT (id)
DO UPDATE SET email=EXCLUDED.email;SELECT
user_id,
SUM(total_cents) FILTER (WHERE total_cents > 10000) AS high,
SUM(total_cents) FILTER (WHERE total_cents <= 10000) AS low
FROM orders GROUP BY 1;SELECT id,total_cents,
SUM(total_cents) OVER (ORDER BY id) run
FROM orders;SELECT id, prev_id, id-prev_id-1 AS gap
FROM (
SELECT id, LAG(id) OVER(ORDER BY id) prev_id
FROM orders
) t WHERE id-prev_id > 1;SELECT percentile_cont(0.9)
WITHIN GROUP (ORDER BY total_cents)
FROM orders;Checklist & conceptual Q&A.
Windows scan once with frame semantics; self-joins duplicate row counts & increase complexity.
PRIMARY KEY = NOT NULL + UNIQUE plus singular table identity; multiple UNIQUE constraints allowed.
Generally beneficial for selectivity; downside is write amplification & larger index memory footprint.
Reveal access paths (seq vs index), join algorithms, row estimates; mismatches hint statistics problems.